﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Text;
using System.Web.UI.WebControls;
using System.IO;

//using EuphoricNation.WebControls;

namespace EuphoricNation.Util
{
    /// <summary>
    /// Extensions for various classes
    /// </summary>
    public static class Extensions
    {
        /// <summary>
        /// Concatenate a string array into a single string, joining elements with 'join'
        /// </summary>
        /// <param name="array"></param>
        /// <param name="join">String to put between elements</param>
        /// <returns>Concatenated string</returns>
        public static string Concatenate(this string[] array, string join)
        {
            StringBuilder output = new StringBuilder();

            // Join everything together
            foreach (string str in array)
            {
                output.Append(str);
                output.Append(join);
            }

            // Remove the last join
            output.Remove(output.Length - join.Length, join.Length);

            return output.ToString();
        }

        /// <summary>
        /// Concatenate a string array into a single string, joining elements with 'join'
        /// </summary>
        /// <param name="array"></param>
        /// <param name="join">Character to put between elements</param>
        /// <returns>Concatenated string</returns>
        public static string Concatenate(this string[] array, char join)
        {
            StringBuilder output = new StringBuilder();

            // Join everything together
            foreach (string str in array)
            {
                output.Append(str);
                output.Append(join);
            }

            // Remove the last join
            output.Remove(output.Length - 1, 1);

            return output.ToString();
        }

        /// <summary>
        /// Concatenate a string array into a single string
        /// </summary>
        /// <param name="array"></param>
        /// <returns>Concatenated string</returns>
        public static string Concatenate(this string[] array)
        {
            StringBuilder output = new StringBuilder();

            // Join everything together
            foreach (string str in array)
            {
                output.Append(str);
            }

            return output.ToString();
        }

        /// <summary>
        /// Trim leading and ending blank entries
        /// </summary>
        /// <param name="array"></param>
        /// <returns>Trimmed array</returns>
        public static string[] TrimBlank(this string[] array)
        {
            List<string> result = new List<string>();
            int firstIndex = 0;
            int lastIndex = 0;
            int len = array.Length;

            for (int i = 0; i < len; ++i)
            {
                if (array[i].Trim().Length > 0)
                {
                    firstIndex = i;
                    break;
                }
            }

            for (lastIndex = firstIndex; lastIndex < len; ++lastIndex)
            {
                if (array[lastIndex].Trim().Length == 0)
                    break;
            }

            for (int i = firstIndex; i < lastIndex; ++i)
                result.Add(array[i]);

            return result.ToArray();
        }

        /// <summary>
        /// Space out text in camel-case
        /// </summary>
        /// <param name="input">Text to convert</param>
        /// <returns>Spaced out text</returns>
        public static string SpaceOutCamel(this string input)
        {
            // TODO: Replace with regex
            for (int i = 1; i < input.Length; ++i)
            {
                if (char.IsUpper(input[i]))
                {
                    input = string.Format("{0} {1}", input.Substring(0, i), input.Substring(i, input.Length - i));
                    ++i;
                }
            }

            return input;
        }

        /// <summary>
        /// Select the specified value within the dropdown list
        /// </summary>
        /// <param name="ddl">Dropdown list to select value</param>
        /// <param name="value">Value to select</param>
        /// <returns>Value found and selected</returns>
        public static bool SelectValue(this DropDownList ddl, string value)
        {
            int i, len = ddl.Items.Count;
            int selectIndex = -1;
            bool success = false;

            for (i = 0; i < len; ++i)
            {
                if (ddl.Items[i].Value == value)
                {
                    selectIndex = i;
                    success = true;
                    break;
                }
            }

            if (success)
                ddl.SelectedIndex = selectIndex;

            return success;
        }

        /// <summary>
        /// Select the specified value within the dropdown list
        /// </summary>
        /// <param name="ddl">Dropdown list to select value</param>
        /// <param name="value">Value to select</param>
        /// <returns>Value found and selected</returns>
        public static bool SelectValue(this DropDownList ddl, int value)
        {
            return SelectValue(ddl, value.ToString());
        }

        /// <summary>
        /// Select the specified name within the dropdown list
        /// </summary>
        /// <param name="ddl">Dropdown list to select value</param>
        /// <param name="name">Name to select</param>
        /// <returns>Name found and selected</returns>
        public static bool SelectName(this DropDownList ddl, string name)
        {
            int i, len = ddl.Items.Count;
            int selectIndex = -1;
            bool success = false;

            for (i = 0; i < len; ++i)
            {
                if (ddl.Items[i].Text == name)
                {
                    selectIndex = i;
                    success = true;
                    break;
                }
            }

            if (success)
                ddl.SelectedIndex = selectIndex;

            return success;
        }

        /// <summary>
        /// Select a specified name within the listcontrol
        /// </summary>
        /// <param name="lc">Listcontrol to select name</param>
        /// <param name="name">Name to select</param>
        /// <param name="exclusive">Should this be the ONLY selection in the list control?</param>
        /// <returns>Name found and selected</returns>
        public static bool SelectName(this ListControl lc, string name, bool exclusive)
        {
            int i, len = lc.Items.Count;
            bool success = false;

            for (i = 0; i < len; ++i)
            {
                if (lc.Items[i].Text != name && exclusive)
                    lc.Items[i].Selected = false;
                else if (lc.Items[i].Text == name)
                {
                    lc.Items[i].Selected = true;
                    success = true;

                    if (!exclusive)
                        break;
                }
            }

            return success;
        }

        /// <summary>
        /// Select a value within a listcontrol
        /// </summary>
        /// <param name="lc">List control</param>
        /// <param name="value">Value to select</param>
        /// <param name="exclusive">Should this be the ONLY selection in the list control?</param>
        /// <returns>Value found and selected</returns>
        public static bool SelectValue(this ListControl lc, string value, bool exclusive)
        {
            int i, len = lc.Items.Count;
            bool success = false;

            for (i = 0; i < len; ++i)
            {
                if (lc.Items[i].Value != value && exclusive)
                    lc.Items[i].Selected = false;
                else if (lc.Items[i].Value == value)
                {
                    lc.Items[i].Selected = true;
                    success = true;

                    if (!exclusive)
                        break;
                }
            }

            return success;
        }

        /// <summary>
        /// Check if dropdownlist has specified value
        /// </summary>
        /// <param name="ddl">Dropdownlist to search</param>
        /// <param name="value">Value to find</param>
        /// <returns>Value found</returns>
        public static bool HasValue(this DropDownList ddl, string value)
        {
            int i, len = ddl.Items.Count;

            for (i = 0; i < len; ++i)
            {
                if (ddl.Items[i].Value == value)
                    return true;
            }

            return false;
        }

        /// <summary>
        /// Check if a dropdownlist has an item with the specified text
        /// </summary>
        /// <param name="ddl">Dropdownlist to search</param>
        /// <param name="value">Text to find</param>
        /// <returns>Text found</returns>
        public static bool HasText(this DropDownList ddl, string value)
        {
            int i, len = ddl.Items.Count;

            for (i = 0; i < len; ++i)
            {
                if (ddl.Items[i].Text == value)
                    return true;
            }

            return false;
        }

        /// <summary>
        /// Check if Listbox has specified value
        /// </summary>
        /// <param name="lb">Listbox to search</param>
        /// <param name="value">Value to find</param>
        /// <returns>Value found</returns>
        public static bool HasValue(this ListBox lb, int value)
        {
            int i, len = lb.Items.Count;
            string str = value.ToString();

            for (i = 0; i < len; ++i)
            {
                if (lb.Items[i].Value == str)
                    return true;
            }

            return false;
        }

        /// <summary>
        /// Check if Listbox has specified value
        /// </summary>
        /// <param name="lb">Listbox to search</param>
        /// <param name="value">Value to find</param>
        /// <returns>Value found</returns>
        public static bool HasValue(this ListBox lb, string value)
        {
            int i, len = lb.Items.Count;
            for (i = 0; i < len; ++i)
            {
                if (lb.Items[i].Value == value)
                    return true;
            }

            return false;
        }

        /// <summary>
        /// Get the value of the item, as an integer
        /// </summary>
        /// <param name="li">Listitem to get int value from</param>
        /// <returns>Value as integer, -1 if value invalid</returns>
        public static int ValueAsInt(this ListItem li)
        {
            try
            {
                return Convert.ToInt32(li.Value);
            }
            catch (Exception)
            {
                return -1;
            }
        }

        /// <summary>
        /// Find a control, recursively
        /// </summary>
        /// <param name="control">Control to search</param>
        /// <param name="id">ID of control</param>
        /// <returns>Matching control (if found)</returns>
        public static Control FindControlRecursive(this Control control, string id)
        {
            return FindControlRecursive(control.Controls, id);
        }

        /// <summary>
        /// Find a control recursively
        /// </summary>
        /// <param name="collection">Collection to search</param>
        /// <param name="id">ID of control to find</param>
        /// <returns>Control if found</returns>
        private static Control FindControlRecursive(ControlCollection collection, string id)
        {
            foreach (Control control in collection)
            {
                if (control.ID == id)
                    return control;

                if (control.Controls.Count > 0)
                {
                    Control ctrl = FindControlRecursive(control.Controls, id);
                    if (ctrl != null)
                        return ctrl;
                }
            }

            return null;
        }

        /// <summary>
        /// Convert a string to an int
        /// </summary>
        /// <param name="str">String to conver to int</param>
        /// <returns>String converted to an int</returns>
        public static int ToInt(this string str)
        {
            return Convert.ToInt32(str);
        }

        /// <summary>
        /// Get a random entry from a list
        /// </summary>
        /// <typeparam name="T">Item type within the list</typeparam>
        /// <param name="list">List with items</param>
        /// <returns>Random item</returns>
        public static T RandomOrDefault<T>(this IList<T> list)
        {
            if (list.Count > 0)
            {
                Random rand = new Random();
                int index = rand.Next(0, list.Count);

                return list[index];
            }
            else
                return default(T);
        }

        /// <summary>
        /// Select a specific node in the tree
        /// </summary>
        /// <param name="nodes">Nodes to search</param>
        /// <param name="value">Value to select</param>
        public static void SelectNode(this TreeNodeCollection nodes, string value)
        {
            foreach (TreeNode node in nodes)
                SelectNode(node, value);
        }

        private static void SelectNode(TreeNode node, string value)
        {
            if (node.Value == value)
                node.Selected = true;
            else
                node.Selected = false;

            foreach (TreeNode thisNode in node.ChildNodes)
                SelectNode(thisNode, value);
        }
    }
}